package top.jacktgq.hsp.nio.buffer_channel;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @Author CandyWall
 * @Date 2020/11/11--12:06
 * @Description 使用一个Buffer完成文件的拷贝
 *                  将file01.txt中的内容拷贝到file03.txt中
 */
public class NIOFileChannel03 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            String str = "hello，糖果墙";
            //创建一个文件输入流
            fis = new FileInputStream(new File("tmp/file01.txt"));

            //通过FileInputStream获取FileChannel
            FileChannel fileInputChannel = fis.getChannel();

            //创建缓冲区ByteBuffer
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

            //创建一个文件输出流
            fos = new FileOutputStream(new File("tmp/file03.txt"));
            //循环读取
            //原因：如果文件中的数据大小是大于缓冲区的大小的，那么缓冲区一次无法接收所有的内容，所以需要循环读取
            while (true) {
                //这里有一个重要的操作，一定不要忘了
                byteBuffer.clear(); //清空ByteBuffer，这句代码必须要写
                /*
                    clear中对下面几个变量进行了复位:
                    position = 0;
                    limit = capacity;
                    mark = -1;
                    如果不进行复位，那么后面将不会有read == -1的情况（一直是read == 0）出现，
                    每write一次，position和limit都会相等（意味着ByteBuffer已经写满了，没地方存新读入的数据了）
                    ，导致下一次读到的字节个数始终为0，所以才会出现read == 0，程序陷入死循环无法退出
                    因此对limit和position进行复位是必要的操作，是对下次数据的读入做准备
                 */

                //将fileInputChannel中的内容读入缓冲区
                int read = fileInputChannel.read(byteBuffer);
                if (read == -1) {
                    break;
                }

                //通过FileOutputStream获取FileChannel
                FileChannel fileOutputChannel = fos.getChannel();

                //将缓冲区的position指针复位
                byteBuffer.flip();

                //将缓冲区中的内容写入fileOutputChannel中
                fileOutputChannel.write(byteBuffer);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭文件输入流
                fis.close();
                //关闭文件输出流
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
